package com.sd365.permission.centre.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.sd365.common.core.annotation.stuffer.CommonFieldStuffer;
import com.sd365.common.core.annotation.stuffer.IdGenerator;
import com.sd365.common.core.annotation.stuffer.MethodTypeEnum;
import com.sd365.common.core.common.aop.MyPageInfo;
import com.sd365.common.core.common.exception.BusinessException;
import com.sd365.common.core.common.exception.code.BizErrorCode;
import com.sd365.common.core.common.exception.code.CommonErrorCode;
import com.sd365.common.core.context.BaseContextHolder;
import com.sd365.common.core.mq.ActionType;
import com.sd365.common.core.mq.MqDataSyncMsg;
import com.sd365.common.util.BeanException;
import com.sd365.common.util.BeanUtil;
import com.sd365.permission.centre.dao.mapper.CompanyMapper;
import com.sd365.permission.centre.dao.mapper.DepartmentMapper;
import com.sd365.permission.centre.dao.mapper.OrganizationMapper;

import com.sd365.permission.centre.entity.Company;
import com.sd365.permission.centre.entity.Department;
import com.sd365.permission.centre.entity.Organization;

import com.sd365.permission.centre.pojo.dto.OrganizationDTO;
import com.sd365.permission.centre.pojo.query.OrganizationQuery;
import com.sd365.permission.centre.pojo.vo.OrganizationStructureVO;
import com.sd365.permission.centre.service.OrganizationService;
import com.sd365.permission.centre.service.util.SendMQMessageUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import com.sd365.permission.centre.service.exception.UserCentreExceptionCode;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang3.ObjectUtils.*;

/**
 * @className: OrganizationServiceImpl
 * @description:
 * @author: 何浪
 * @date: 2020/12/11 17:58
 */
@Service
public class OrganizationServiceImpl extends AbstractBaseDataServiceImpl implements OrganizationService {
    private static final Logger log = LoggerFactory.getLogger(OrganizationService.class);
    @Autowired
    private OrganizationMapper organizationMapper;
    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private SendMQMessageUtil sendMQMessageUtil;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private DepartmentMapper departmentMapper;
    /**
     * 交换机名称
     */
    private static final String EXCHANGE_NAME = "directs";
    /**
     * 路由KEY
     */
    private static final String ROUTE_KEY = "organization";
    /**
     * 数据表名
     */
    private static final String TABLE_NAME = "organization";

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.ADD)
    public Boolean add(@Valid OrganizationDTO organizationDTO) {
            Organization organization = BeanUtil.copy(organizationDTO, Organization.class);
            organization.setId(idGenerator.snowflakeId());

            super.baseDataStuff4Add(organization);
            Boolean flag = organizationMapper.insert(organization) > 0;
            if (flag) {
                sendMQMessageUtil.SendMessage(ActionType.INSERT, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, organization);
            }
            return flag;
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.DELETE)
    public Boolean remove(Long id, Long version) {
            Example example = new Example(Organization.class);
            example.createCriteria().andEqualTo("id", id).andEqualTo("version", version);
            Organization organization = new Organization();
            organization.setId(id);
            organization.setVersion(version);

            Boolean flag = organizationMapper.deleteByExample(example) > 0;
            if (flag) {
                sendMQMessageUtil.SendMessage(ActionType.DELETE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, organization);
            }
            return flag;

    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.UPDATE)
    public Boolean modify(OrganizationDTO organizationDTO) {
            organizationDTO.setUpdatedTime(new Date());
            Organization organization = BeanUtil.copy(organizationDTO, Organization.class);
            Example example = new Example(Organization.class);
            super.baseDataStuff4Updated(organization);
            example.createCriteria().andEqualTo("id", organizationDTO.getId()).andEqualTo("version", organizationDTO.getVersion());
            Boolean flag = organizationMapper.updateByExample(organization, example) > 0;
            if (flag) {
                sendMQMessageUtil.SendMessage(ActionType.UPDATE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, organization);
            }
            return flag;

    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    public List<OrganizationDTO> commonQuery(OrganizationQuery organizationQuery) {
        if (organizationQuery == null) {
            throw new BusinessException(BizErrorCode.PARAM_VALID_FIELD_REQUIRE, new Exception("commonQuery 方法参数不能为null"));
        }
            Organization organization = BeanUtil.copy(organizationQuery, Organization.class);
            List<Organization> organizations = organizationMapper.commonQuery(organization);
            Page page = (Page) organizations;
            log.info(page.toString());
            BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
            //对象转化 po list to dto list
            List<OrganizationDTO> organizationDTOS = BeanUtil.copyList(organizations, OrganizationDTO.class, new BeanUtil.CopyCallback() {

                @Override
                public void copy(Object o, Object o1) {
                    // 调用 BeanUtil.copyProperties
                    if (o == null || o1 == null) {
                        throw new BeanException("拷贝对象不可以为空", new Exception("copyList 拷贝回调错误"));
                    }
                    Organization driver = (Organization) o;
                    OrganizationDTO driverDTO = (OrganizationDTO) o1;
                }
            });
            return organizationDTOS;
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    public OrganizationDTO queryById(Long id) {
            OrganizationDTO organizationDTO = null;
            Organization organization = organizationMapper.selectByPrimaryKey(id);
            if (organization != null) {
                organizationDTO = BeanUtil.copy(organization, OrganizationDTO.class);
            }
            return organizationDTO;

    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.ADD)
    public OrganizationDTO copy(Long id) {
        Organization organization = organizationMapper.selectByPrimaryKey(id);
        if (organization != null) {
            OrganizationDTO copy = BeanUtil.copy(organization, OrganizationDTO.class);
            return copy;
        }
        return new OrganizationDTO();
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.DELETE)
    public Boolean batchDelete(OrganizationDTO[] organizationDTOS) {
        Assert.notEmpty(organizationDTOS, "批量删除参数不可以为空");
        for (OrganizationDTO organizationDTO : organizationDTOS) {
            Example example = new Example(Organization.class);
            example.createCriteria().andEqualTo("id", organizationDTO.getId()).andEqualTo("version", organizationDTO.getVersion());
            Boolean result = organizationMapper.deleteByExample(example) > 0;
            Assert.isTrue(result, String.format("删除的记录id %d 没有匹配到版本", organizationDTO.getId()));
            if (result) {
                Organization organization = new Organization();
                organization.setId(organizationDTO.getId());
                organization.setVersion(organization.getVersion());
                sendMQMessageUtil.SendMessage(ActionType.DELETE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, organization);
            }

        }
        return true;
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.UPDATE)
    public Boolean batchUpdate(OrganizationDTO[] organizationDTOS) {
        Assert.noNullElements(organizationDTOS, "更新数组不能为空");
        for (OrganizationDTO organizationDTO : organizationDTOS) {
            Organization organization = BeanUtil.copy(organizationDTO, Organization.class);
            Example example = new Example(organization.getClass());
            example.createCriteria().andEqualTo("id", organizationDTO.getId()).andEqualTo("version", organizationDTO.getVersion());
            super.baseDataStuff4Updated(organization);
            Boolean result = organizationMapper.updateByExampleSelective(organization, example) > 0;
            Assert.isTrue(result, "没有找到相应id更新记录");
            if (result) {
                sendMQMessageUtil.SendMessage(ActionType.UPDATE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, organization);
            }
        }
        return true;
    }

    @Override
    public List<OrganizationStructureVO> structureVoQueryById(Long id) {
        List<OrganizationStructureVO> result = new ArrayList<>();
        List<Company> companies;
        if (isNotEmpty(id)) {
            companies = companyMapper.findAllByOrgId(id);
        } else {
            companies = companyMapper.selectAll();
        }
        if (!CollectionUtils.isEmpty(companies)) {
            for (Company company : companies) {
                OrganizationStructureVO organizationStructureVO = new OrganizationStructureVO();
                organizationStructureVO.setId(company.getId());
                organizationStructureVO.setLabel(company.getName());
                //筛选一级部门
                List<Department> firstDepartmentList = departmentMapper.selectByCompanyId(company.getId());
                List<OrganizationStructureVO> firstChildrens = new ArrayList<>();
                if (!CollectionUtils.isEmpty(firstDepartmentList)) {
                    for (Department department : firstDepartmentList) {
                        OrganizationStructureVO firstChildren = new OrganizationStructureVO();
                        firstChildren.setId(department.getId());
                        firstChildren.setLabel(department.getName());
                        firstChildren.setChildren(getDepartmentNode(department.getId()));
                        firstChildrens.add(firstChildren);
                    }
                }
                organizationStructureVO.setChildren(firstChildrens);
                result.add(organizationStructureVO);
            }
        } else {
            return new ArrayList<>();
        }
        return result;
    }

    /**
     * 通过递归方式获取子部门
     *
     * @param id
     * @return
     */
    private List<OrganizationStructureVO> getDepartmentNode(Long id) {
        List<OrganizationStructureVO> result = new ArrayList<>();
        List<Department> treeDepartmentList = departmentMapper.selectByParentId(id);
        if (!CollectionUtils.isEmpty(treeDepartmentList)) {
            for (Department department : treeDepartmentList) {
                OrganizationStructureVO organizationStructureVO = new OrganizationStructureVO();
                organizationStructureVO.setId(department.getId());
                organizationStructureVO.setLabel(department.getName());
                organizationStructureVO.setChildren(getDepartmentNode(department.getId()));
                result.add(organizationStructureVO);
            }
        } else {
            return new ArrayList<>();
        }
        return result;
    }
}
